package dai.basic.glfw

import org.lwjgl.glfw.GLFW
import org.lwjgl.glfw.GLFWErrorCallback
import org.lwjgl.opengl.GL
import org.lwjgl.opengl.GL11C.*
import org.lwjgl.opengl.GLUtil
import org.lwjgl.system.Configuration
import org.lwjgl.system.MemoryUtil
import java.lang.IllegalStateException
import java.lang.RuntimeException

fun main() {

    // 开启debug mode
    Configuration.DEBUG.set(true)
    Configuration.DEBUG_LOADER.set(false)
    Configuration.DEBUG_MEMORY_ALLOCATOR.set(false)
    Configuration.DEBUG_STACK.set(false)

    // set error callback and init glfw
    val errCallback = GLFWErrorCallback.createPrint(System.err)
    GLFW.glfwSetErrorCallback(errCallback)
    if (!GLFW.glfwInit()) {
        throw IllegalStateException("unable to init glfw!")
    }

    // window settings
    val title = "FirstWindow"
    val width = 640
    val height = 480
    val resizeable = true
    GLFW.glfwDefaultWindowHints()  // default window setting
    GLFW.glfwWindowHint(GLFW.GLFW_VISIBLE, GLFW.GLFW_TRUE)
    GLFW.glfwWindowHint(GLFW.GLFW_RESIZABLE, if (resizeable) GLFW.GLFW_TRUE else GLFW.GLFW_FALSE)
    GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_DEBUG_CONTEXT, GLFW.GLFW_TRUE)

    // create window
    val window = GLFW.glfwCreateWindow(width, height, title, MemoryUtil.NULL, MemoryUtil.NULL)
    if (window == MemoryUtil.NULL) {
        throw RuntimeException("fail to create window!")
    }

    // set keyboard input callback
    val keyCallback = GLFW.glfwSetKeyCallback(window){win,key,scancode,action,mods->
        if (key == GLFW.GLFW_KEY_ESCAPE && action == GLFW.GLFW_RELEASE){
            GLFW.glfwSetWindowShouldClose(win,true)
        }

        when(key){
            // 上
            GLFW.GLFW_KEY_UP,
            GLFW.GLFW_KEY_W
            -> {
                when(action){
                    GLFW.GLFW_PRESS-> println("up pressed")
                    GLFW.GLFW_RELEASE-> println("up released")
                }
            }

            // 下
            GLFW.GLFW_KEY_DOWN,
            GLFW.GLFW_KEY_S
            -> {
                when(action){
                    GLFW.GLFW_PRESS-> println("down pressed")
                    GLFW.GLFW_RELEASE-> println("down released")
                }
            }
        }
    }

    // set mouse callback
    // 鼠标按钮事件
    val mouseCallback = GLFW.glfwSetMouseButtonCallback(window){win,button,action,mods->
        if (button == GLFW.GLFW_MOUSE_BUTTON_1 && action == GLFW.GLFW_PRESS){
            println("鼠标左键按下!")
        }
    }
    // 鼠标位置
    val cursorPosCallback = GLFW.glfwSetCursorPosCallback(window){win,xpos,ypos->
        println("x:${xpos.toInt()},y:${ypos.toInt()}")
    }

    // 鼠标进入窗口
    val cursorEnterCallback = GLFW.glfwSetCursorEnterCallback(window){win,entered->
        println("================鼠标是否进入窗口? entered:${entered}")
    }

    // glfwSwapInterval needs a context on the calling thread, otherwise will cause NO_CURRENT_CONTEXT error
    GLFW.glfwMakeContextCurrent(window)

    // Will let lwjgl know we want to use this context as the context to draw with
    GL.createCapabilities()

    // opengl debug context
    val debugProc = GLUtil.setupDebugMessageCallback()
    if (debugProc != null){
        println("debugProc is not null")
    }

    // // How many draws to swap the buffer
    GLFW.glfwSwapInterval(1)

    // Shows the window
    GLFW.glfwShowWindow(window)

    println(" end setting window and show,ready to loop")

    // opengl env settting
    glClearColor(0f, 1f, 1f, 1f)

    while (!GLFW.glfwWindowShouldClose(window)) {
        glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT)

        GLFW.glfwSwapBuffers(window)
        GLFW.glfwPollEvents()
    }
    cursorEnterCallback?.free()
    cursorPosCallback?.free()
    keyCallback?.free()
    mouseCallback?.free()
    debugProc?.free()
    errCallback.free()
    GLFW.glfwTerminate()
    println("----------exit success---")
}